use crate::model::user::User;
use crate::service::user::UserDao;
use crate::state::AppState;
use crate::utils::jwt::{create_token, Claims};
use crate::utils::password;
use crate::utils::result::{data, error, success};
use axum::http::{HeaderMap, HeaderValue};
use axum::response::IntoResponse;
use axum::{Extension, Json};
use axum_valid::Valid;
use captcha::filters::{Dots, Noise, Wave};
use captcha::Captcha;
use tower_sessions::Session;

pub async fn login(
    Extension(state): Extension<AppState>,
    session: Session,
    Json(user): Json<User>,
) -> impl IntoResponse {
    let password = user.password.expect("用户输入密码异常");

    match UserDao::new(&state.db_pool)
        .select_by_account(&user.account)
        .await
    {
        Ok(db_user) => {
            let session_captcha = session.get("captcha").await.unwrap_or_default();
            if session_captcha.is_none() {
                return error("验证码已过期");
            } else if user.captcha != session_captcha {
                return error("验证码错误");
            }
            if password::verify(&password, &db_user.password.unwrap_or_default()) {
                let token: String =
                    create_token(&Claims::new(user.account, db_user.username.unwrap()));
                return data(token, "登录成功");
            }
            error("密码有错误")
        }
        Err(err) => {
            println!("{}", err);
            error("账号不存在")
        }
    }
}
pub async fn register(
    Extension(state): Extension<AppState>,
    Valid(Json(mut user)): Valid<Json<User>>,
) -> impl IntoResponse {
    let user_dao = UserDao::new(&state.db_pool);
    if user_dao.account_is_exist(&user.account).await {
        return error("账号已经存在！");
    }
    let password = user.password.unwrap();
    user.password = Some(password::hash(password.as_str()));
    user_dao.add(user).await;
    success("注册成功!")
}

pub async fn captcha(session: Session) -> (HeaderMap, impl IntoResponse) {
    // 返回(验证码, 图片)
    let captcha = Captcha::new()
        .add_chars(5)
        .apply_filter(Noise::new(0.4))
        .apply_filter(Wave::new(2.0, 20.0).horizontal())
        .apply_filter(Wave::new(2.0, 20.0).vertical())
        .view(220, 120)
        .apply_filter(Dots::new(15))
        .as_tuple()
        .unwrap();
    println!("captcha: {}", captcha.0);
    session.insert("captcha", captcha.0).await.unwrap();
    // format!("data:image/png;base64,{}", base64::encode(captcha.1))
    let mut header_map = HeaderMap::new();
    header_map.insert("content-type", HeaderValue::from_static("image/png"));
    (header_map, captcha.1)
}
